import {computed, delay, designComponent, designPage, Fragment, onMounted, reactive, useRefs} from "@peryl/react-compose";
import {usePageConfig} from "../../micro/MicroApp.pageConfig";
import {$ai, $dialog, $file, $imageSelector, $message, $notice, $previewer, Box, Button, ButtonGroup, ColorPicker, Dropdown, DropdownOption, Icon, Input, PageCard, PageCardContent, PageCardTitle, Scroll, Space, Tooltip} from "plain-design";
import './resume-generator-detail-page.scss';
import {usePageService} from "../../modules/micro/usePageService";
import {ReactCmsRender} from "../components/ReactCmsRender";
import {base64toFile, CmsIcons, getValueByPath, PlainCmsNamespace, setValueByPath} from "@peryl/react-cms-editor";
import {DEMO_RESUME_DATA} from "./resume.data";
import {deepcopy} from "@peryl/utils/deepcopy";
import {debounce} from "@peryl/utils/debounce";
import {chunk} from "@peryl/utils/chunk";
import {AiResumeSystemPrompt, AiResumeTranslatePrompt, getAiResumeUserPrompt, ResumeFormItem} from "./AiResumeGenerator.utils";
import {AIConfigOptions} from "../../modules/AIConfigs";
import {createJsonStreamHandler} from "../ai/createJsonStreamHandler";
import {iResume} from "./resume.type";
import {throttle} from "@peryl/utils/throttle";
import html2canvas from "html2canvas";
import {DefaultGetSnapshot} from "../../modules/cms-visual-editor";
import {exportElement2Pdf} from "./exportElement2Pdf";
import {iResumeRecord} from "./resume.utils";
import {saveResume} from "./saveResume";
import {decodeResumeRecord} from "./decodeResumeRecord";
import {http} from "../../modules/plain-design/http";
import {pathJoin} from "@peryl/utils/pathJoin";
import {env} from "../../env";
import {checkValueByDescription, createArrayFieldDescription, createDescription, createObjectFieldDescription} from "./DataDescription";

export default designPage(() => {

  usePageConfig(config => {config.hideNavigation = true;});

  const { nav, pageParam } = usePageService();

  let sourceResumeRecord: iResumeRecord | undefined = deepcopy(pageParam.resume);
  const sourceDecodeData = decodeResumeRecord(sourceResumeRecord);

  const { refs, onRef } = useRefs({ scroll: Scroll });

  const SOURCE_RESUME_INFO = DEMO_RESUME_DATA;

  const state = reactive({
    /*当前模板数据*/
    templateMetas: sourceDecodeData.dataMetas ?? [],
    /*当前简历数据*/
    /*todo 这里深度复制一遍resumeInfo，避免与sourceDecodeData.dataMetas中的rootMeta使用同一个resumeInfo对象，使用同一个对象的情况下会导致编辑resumeInfo值的时候出现卡顿问题，应该是对同一个变量多次proxy导致的问题*/
    resumeInfo: deepcopy(sourceDecodeData.resumeInfo ?? SOURCE_RESUME_INFO),

    /*当前是否正在处理AI生成简历数据*/
    aiGenerating: false,
    /*当前是否正在导出*/
    exporting: false,
    /*当前是否正在进行AI文本润色*/
    valueLoading: {} as Record<string, boolean | undefined>,
    /*当前是否正在进行AI翻译*/
    translating: false,
    /*当前是否正在保存*/
    saving: false,
    /*是否正在上传文件*/
    uploading: false,

    /*渲染控制*/
    currentCmsRender: 'a' as 'a' | 'b',
    cmsRenderKey: { a: 1, b: 1, }
  });

  const cmsRenderKey_a = computed(() => 'a' + state.cmsRenderKey.a);
  const cmsRenderKey_b = computed(() => 'b' + state.cmsRenderKey.b);

  /**
   * 渲染两个CmsRender，因为更新resumeInfo的时候，没有办法更新cms内容，只能通过key的方式令CmsRender刷新；
   * 只渲染一个CmsRender的情况下，通过key来刷新CmsRender的时候，CmsRender在销毁重新渲染的一瞬间因为失去高度，
   * 导致滚动位置回到顶部，即使记下scrollTop，在CmsRender的时候重新应用这个scrollTop，也会出现闪烁的问题；
   * 这里渲染两个CmsRender，当需要更新渲染内容的时候，让隐藏的那个CmsRender刷新，刷新完之后；正在显示的没有更新的CmsRender隐藏；隐藏的已经更新内容的显示；
   * 因为两者高度几乎相同，所以不会出现滚动位置变化的问题，也不会有闪烁的问题
   * @author  韦胜健
   * @date    2025/5/20 19:14
   */
  const _refreshRenderKey = async () => {
    if (state.currentCmsRender === 'a') {
      state.cmsRenderKey.b++;
      await delay(78);
      state.currentCmsRender = 'b';
    } else {
      state.cmsRenderKey.a++;
      await delay(78);
      state.currentCmsRender = 'a';
    }
  };
  const refreshRenderKey = debounce(_refreshRenderKey, 100);
  const throttleScrollBottom = throttle(() => refs.scroll!.methods.scrollEnd(), 500);

  /**
   * 替换模板中的简历信息为编辑中的简历信息数据
   * @author  韦胜健
   * @date    2025/5/20 19:21
   */
  const dataMetas = computed((): PlainCmsNamespace.iDataMeta[] => {
    return state.templateMetas.map((item): PlainCmsNamespace.iDataMeta => {
      if (!!item.parentId) {return item;}
      const rootMeta = deepcopy(item);
      if (!rootMeta.binding) {
        console.log({ rootMeta });
        $notice.error('RootMeta has no binding.');
        return rootMeta;
      }
      rootMeta.binding.resume.bindingSource.data = state.resumeInfo;
      return rootMeta;
    });
  });

  const handler = {
    /**
     * 将流式响应的简历数据更新到页面
     * @author  韦胜健
     * @date    2025/5/21 12:09
     */
    updateStateResumeInfo: (responseResumeData: Partial<iResume>) => {
      responseResumeData = deepcopy(responseResumeData);
      if (!responseResumeData) {return;}
      // const { primary, secondary, avatar, basicInfo } = state.resumeInfo;

      const ResumeDescription = createDescription({
        title: { type: String, default: () => state.resumeInfo.title /*保留简历标题*/ },
        primary: { type: String, default: () => state.resumeInfo.primary /*保留主题色*/ },
        secondary: { type: String, default: () => state.resumeInfo.secondary /*保留次级色*/ },
        avatar: { type: String, default: () => state.resumeInfo.avatar /*保留头像地址*/ },
        basicInfo: createObjectFieldDescription(
          {
            title: { type: String, default: () => state.resumeInfo.basicInfo.title /*保留基础信息标题*/ },
            data: createArrayFieldDescription(
              { label: String, type: String, val: String, icon: String },
              () => []/*自动初始化basicInfo.data*/
            )
          },
          () => ({})/*自动初始化basicInfo*/
        ),
        education: createObjectFieldDescription(
          {
            title: { type: String, default: () => state.resumeInfo.education.title /*保留教育经历标题*/ },
            data: createArrayFieldDescription(
              { time: String, school: String, program: String, content: createArrayFieldDescription(String, () => []/*自动初始化 education.data.?.content */), },
              () => []/*自动初始化education.data*/
            )
          },
          () => ({})/*自动初始化education*/
        ),
        experience: createObjectFieldDescription(
          {
            title: { type: String, default: () => state.resumeInfo.experience.title /*保留工作经历标题*/ },
            data: createArrayFieldDescription(
              { time: String, company: String, role: String, content: createArrayFieldDescription(String, () => []/*自动初始化experience.data.?content*/), },
              () => []/*自动初始化experience.data*/
            )
          },
          () => ({})/*自动初始化experience*/
        ),
        externals: createArrayFieldDescription(
          {
            title: String,
            content: createArrayFieldDescription(String, () => []/*自动初始化externals?.content*/)
          },
          () => []/*自动初始化externals*/
        )
      });

      /*根据类型描述对象，检查responseResumeData中的属性值，自动初始化有默认值的属性值*/
      const newResumeData: iResume = checkValueByDescription(responseResumeData, ResumeDescription);

      /*基础信息中的子信息数据与标准数据中的基础信息子信息数据合并*/
      newResumeData.basicInfo.data = newResumeData.basicInfo.data.map(item => {
        const oldItem = SOURCE_RESUME_INFO.basicInfo.data.find(i => i?.type === item.type || i?.label === item.label);
        return {
          ...item,
          ...oldItem,
          label: item.label ?? oldItem?.label,
          val: item.val,
        };
      });
      // console.log(newResumeData);

      newResumeData.primary = state.resumeInfo.primary ?? SOURCE_RESUME_INFO.primary;
      newResumeData.secondary = state.resumeInfo.secondary ?? SOURCE_RESUME_INFO.secondary;
      newResumeData.avatar = state.resumeInfo.avatar ?? SOURCE_RESUME_INFO.avatar;

      state.resumeInfo = newResumeData;
    },
    /**
     * AI生成简历数据
     * @author  韦胜健
     * @date    2025/5/20 23:29
     */
    startAIGeneration: async () => {

      state.aiGenerating = true;

      let _fullText = '';
      try {
        const data = await getAiResumeUserPrompt();
        const aiConfigOption = AIConfigOptions.find(i => i.name === data.aiConfigName) ?? AIConfigOptions[0];

        const { getData, handleFullText } = createJsonStreamHandler();
        await $ai.chatStream({
          aiConfig: aiConfigOption.config,
          messages: [
            { role: 'system', content: AiResumeSystemPrompt },
            { role: 'user', content: data.userContent }
          ],
          onReceiving: ({ chunkText }) => {
            _fullText += chunkText;
            // console.log(_fullText.split('\n').slice(-2));
            console.log('_fullText', _fullText);
            _fullText = handleFullText(_fullText).list.join('\n');
            handler.updateStateResumeInfo(getData());
            throttleScrollBottom();
          },
          onFinish: () => {
            $notice.success('已经生成完毕');
            console.log('已经生成完毕');
            refreshRenderKey();
          },
        });
      } catch (e: any) {
        if (!e) {return;}
        console.error(e);
        $notice.error(e.message || JSON.stringify(e));
        // console.log(_fullText);
      } finally {
        state.aiGenerating = false;
      }
    },
    /**
     * AI润色文本
     * @author  韦胜健
     * @date    2025/5/21 11:02
     */
    startAIGenerateText: async (path: string) => {
      state.valueLoading = {
        ...state.valueLoading,
        [path]: true,
      };
      const valuePathList = path.split('.');
      const content = getValueByPath(state.resumeInfo, valuePathList);

      try {
        await $ai.chatStream({
          messages: [
            { role: 'system', content: '你是一名专业的简历文案编辑专家，需要你对用户输入的内容从编写简历的角度出发进行内容润色' },
            { role: 'user', content: content }
          ],
          aiConfig: AIConfigOptions[0].config,
          onReceiving: ({ fullText }) => {
            setValueByPath(state.resumeInfo, valuePathList, fullText);
          },
          onFinish: (fullText) => {
            refreshRenderKey();
            $message.success('润色完毕');
          },
        });
      } finally {
        state.valueLoading = {
          ...state.valueLoading,
          [path]: false,
        };
      }
    },
    /*切换模板*/
    changeTemplate: async () => {
      const data = await http.post<{ list: iResumeRecord[] }>('resume/list', { all: true, filters: [{ field: 'isTemplate', operator: '=', value: 'Y' }] });
      $imageSelector({
        title: '选择模板',
        selectOptions: data.list.map(i => ({ url: i.image ?? '', val: i.id! })),
        imageFit: 'cover',
        imagePosition: 'top left',
        aspectRatio: '3 / 4',
        handleConfirm: async (selectValue) => {
          const selectRecord = data.list.find(i => i.id === selectValue);
          if (!selectRecord?.jsonString) {
            $message.error('该模板数据异常');
            return false;
          }
          try {
            const { dataMetas, resumeInfo } = decodeResumeRecord(selectRecord);
            if (!!dataMetas && !!resumeInfo) {
              state.templateMetas = dataMetas;
              state.resumeInfo.primary = resumeInfo.primary;
              state.resumeInfo.secondary = resumeInfo.secondary;
              await refreshRenderKey();
            }
          } catch (e: any) {
            $message.error('模板数据异常，无法解析' + (e.message || JSON.stringify(e)));
          }
        },
      });
    },
    /*上传职业照*/
    uploadImage: async () => {
      const file = await $file.chooseImage(false);
      state.uploading = true;
      return new Promise<void>(resolve => {
        $file.upload({
          file,
          action: pathJoin(env.baseURL, 'saveFile'),
          filename: 'file',
          onSuccess: (data: any) => {
            state.uploading = false;
            state.resumeInfo.avatar = data.result.path;
            refreshRenderKey();
            resolve();
          },
          onError: (e: any) => {
            state.uploading = false;
            $notice.error(e.message || JSON.stringify(e));
            resolve();
          },
        });
      });
    },
    /**
     * 保存简历信息
     * @author  韦胜健
     * @date    2025/5/21 12:25
     */
    save: async () => {
      await saveResume({
        onStart: () => {state.saving = true;},
        onFinally: () => {state.saving = false;},
        onSuccess: (newResumeRecord) => {sourceResumeRecord = newResumeRecord;},
        image: await exportMethods.getSnapshot() ?? 'NO_IMAGE',
        dataMetas: dataMetas.value,
        sourceResumeRecord,
        isTemplate: 'N'
      });
    },
  };

  const exportMethods = {
    checkData: (): HTMLElement => {
      const cmsEditorPageElement = document.querySelector(`[data-cms-render=${state.currentCmsRender === 'a' ? cmsRenderKey_a.value : cmsRenderKey_b.value}]`) as HTMLDivElement | undefined;
      console.log('cmsEditorPageElement', cmsEditorPageElement);
      if (!cmsEditorPageElement) {
        const msg = `Internal Error, can't find element: data-cms-render element`;
        $notice.error(msg);
        throw new Error(msg);
      }
      return cmsEditorPageElement;
    },
    getSnapshot: async () => {
      const cmsEditorPageElement = exportMethods.checkData();
      const canvas = await html2canvas(cmsEditorPageElement, { useCORS: true });
      const base64 = canvas.toDataURL('image/jpg', 1);
      const file = base64toFile(base64);
      const previewImagePath = await DefaultGetSnapshot({ element: cmsEditorPageElement, file });
      return previewImagePath;
    },
    exportJson: () => {
      $dialog({
        editType: 'textarea',
        editValue: JSON.stringify(dataMetas.value, null, 2),
        editReadonly: true,
      });
    },
    exportImage: async () => {
      await delay(78);
      state.exporting = true;
      try {
        const previewImagePath = await exportMethods.getSnapshot();
        !!previewImagePath && await $previewer.preview(previewImagePath);
      } finally {
        state.exporting = false;
      }
    },
    exportPdf: async () => {
      await delay(78);
      const cmsEditorPageElement = exportMethods.checkData();
      state.exporting = true;
      await delay(3000);
      try {
        await exportElement2Pdf(cmsEditorPageElement);
      } finally {
        state.exporting = false;
      }
    },
  };

  const translateMethods = {
    languageOptions: [
      { name: 'English', promptName: '英语' },
      { name: '日本語', promptName: '日语' },
      { name: 'Français', promptName: '法语' },
      { name: 'Deutsch', promptName: '德语' },
      { name: 'Русский язык', promptName: '俄语' },
    ] as { name: string, promptName: string }[],
    translate: async (languageName: string) => {
      /*先等dropdown关闭*/
      await delay(78);

      state.translating = true;
      const languageOption = translateMethods.languageOptions.find(i => i.name === languageName);
      if (!languageOption) {
        $notice.error(`无法识别语言：${languageName}`);
        return;
      }
      try {

        const { getData, handleFullText } = createJsonStreamHandler();

        await $ai.chatStream({
          aiConfig: AIConfigOptions[0].config,
          messages: [
            { role: 'system', content: AiResumeTranslatePrompt },
            { role: 'user', content: `将如下内容翻译为${languageOption.promptName}\n${JSON.stringify(state.resumeInfo, null, 2)}` }
          ],
          onReceiving: ({ fullText }) => {
            // console.log(_fullText.split('\n').slice(-2));
            handleFullText(fullText);
            handler.updateStateResumeInfo(getData());
            throttleScrollBottom();
          },
          onFinish: (fullText) => {
            console.log(state.resumeInfo);
            $notice.success('已经翻译完毕');
            console.log('已经翻译完毕');
            // console.log(fullText);
            refreshRenderKey();
          },
        });
      } catch (e: any) {
        if (!e) {return;}
        console.error(e);
        $notice.error(e.message || JSON.stringify(e));
        // console.log(_fullText);
      } finally {
        state.translating = false;
      }
    },
  };

  onMounted(async () => {
    /*加载一个模板数据*/
    // const resp = await fetch(buildAssetsPath('resume/template_01.json'));
    // const dataMetas = await resp.json();
    // state.templateMetas = dataMetas;
  });

  const TextGeneratorButton = designComponent({
    props: {
      valuePath: { type: String, required: true },
    },
    setup({ props }) {
      return () => {
        return (
          <Button
            icon="ie-stick"
            loading={!!state.valueLoading[props.valuePath]}
            onClick={() => handler.startAIGenerateText(props.valuePath)}
          />
        );
      };
    },
  });

  return () => (
    <PageCard className="resume-generator-detail-page" full size="small" readonly={state.translating || state.aiGenerating}>
      <PageCardTitle
        v-slots={{
          titleContent: () => (<h2 style={{ margin: 0, display: 'flex', alignItems: 'center' }}><Icon icon="ie-stick"/><span style={{ marginLeft: '0.5em' }}>AI生成简历</span></h2>),
          default: () => <Space>
            <Button label="返回" icon="pi-undo" onClick={() => {nav.back();}}/>
            <ButtonGroup>
              <Button label="导出" icon="ie-export" onClick={exportMethods.exportJson} loading={state.exporting}/>
              <Dropdown
                trigger="hover"
                placement="bottom-end"
                disabled={state.exporting}
                v-slots={{
                  default: () => <Button icon="pi-down" loading={state.exporting}/>,
                  popper: () => <>
                    <DropdownOption label="导出Json" onClick={exportMethods.exportJson}/>
                    <DropdownOption label="导出图片" onClick={exportMethods.exportImage}/>
                    <DropdownOption label="导出PDF" onClick={exportMethods.exportPdf}/>
                  </>
                }}
              />
            </ButtonGroup>
            <Button label="上传职业照" icon="pi-image" asyncHandler={handler.uploadImage}/>
            <Button label="选择模板" icon="pi-bookmark" onClick={handler.changeTemplate}/>
            <Button label="AI生成" icon="ie-stick" loading={state.aiGenerating} onClick={() => {handler.startAIGeneration();}}/>
            <ButtonGroup>
              <Button label="AI翻译" icon="ie-stick" onClick={() => translateMethods.translate(translateMethods.languageOptions[0].name)} loading={state.translating}/>
              <Dropdown
                trigger="hover"
                placement="bottom-end"
                disabled={state.translating}
                v-slots={{
                  default: () => <Button icon="pi-down" loading={state.translating}/>,
                  popper: () => translateMethods.languageOptions.map(option => (
                    <DropdownOption key={option.name} label={option.name} onClick={() => translateMethods.translate(option.name)}/>
                  ))
                }}
              />
            </ButtonGroup>
            <Button mode="fill" label="保存" icon="pi-save" onClick={handler.save} loading={state.saving}/>
          </Space>
        }}/>
      <div className="resume-generator-detail-page-body">
        <PageCard full className="page-body-left">
          <Scroll alwaysShowScrollbar ref={onRef.scroll}>

            {/*---------------------------------------简历信息-------------------------------------------*/}
            <div className="page-body-title">简历信息</div>
            <PageCard>
              <PageCardContent>
                <Space>
                  <ResumeFormItem label="简历标题">
                    <Input v-model={state.resumeInfo.title} onChange={refreshRenderKey}/>
                  </ResumeFormItem>
                </Space>
                <Space style={{ alignItems: 'center' }}>
                  <ResumeFormItem label="简历主题色">
                    <ColorPicker v-model={state.resumeInfo.primary} onChange={refreshRenderKey} noClear/>
                  </ResumeFormItem>
                  <ResumeFormItem label="简历次级色">
                    <ColorPicker v-model={state.resumeInfo.secondary} onChange={refreshRenderKey} noClear/>
                  </ResumeFormItem>
                </Space>
              </PageCardContent>
            </PageCard>

            {/*---------------------------------------基本信息-------------------------------------------*/}
            <div className="page-body-title">基本信息</div>
            <PageCard>
              <PageCardContent>
                <ResumeFormItem label="标题">
                  <Input v-model={state.resumeInfo.basicInfo.title} onChange={refreshRenderKey}/>
                </ResumeFormItem>
              </PageCardContent>
              <PageCardContent>
                {chunk(state.resumeInfo.basicInfo.data, 2).map((list, listIndex) => (
                  <Space key={listIndex}>
                    {list.map((item, index) => {
                      return (
                        <ResumeFormItem label={item.label} key={index} style={{ flex: 1 }}>
                          <Dropdown
                            v-slots={{
                              default: () => <Button>{!item.icon ? <Icon icon="pi-question"/> : <div className={item.icon}/>}</Button>,
                              popper: () => (
                                <div className="icon-list-panel">
                                  {chunk(CmsIcons, 6).map((list, listIndex) => (
                                    <div key={listIndex}>
                                      {list.map(icon => (
                                        <Box
                                          key={icon}
                                          className={`icon-list-item ${icon} ${icon === item.icon ? 'icon-is-selected' : ''}`}
                                          onClick={() => {
                                            item.icon = icon;
                                            refreshRenderKey();
                                          }}
                                        />
                                      ))}
                                    </div>
                                  ))}
                                </div>
                              )
                            }}/>
                          <Input v-model={item.val} onChange={refreshRenderKey}/>
                        </ResumeFormItem>
                      );
                    })}
                    {new Array(2 - list.length).fill(0).map((_, index) => (
                      <div style={{ flex: 1 }} key={index}/>
                    ))}
                  </Space>
                ))}
              </PageCardContent>
            </PageCard>

            {/*---------------------------------------教育经历-------------------------------------------*/}
            <div className="page-body-title">教育经历</div>
            <PageCard>
              <PageCardContent>
                <ResumeFormItem label="标题">
                  <Input v-model={state.resumeInfo.education.title} onChange={refreshRenderKey}/>
                </ResumeFormItem>
              </PageCardContent>
              {state.resumeInfo.education.data.map((educationItem, educationIndex) => {
                return (
                  <PageCardContent key={educationIndex}>
                    <div className="page-group-title">
                      {[educationItem.school, educationItem.program].filter(Boolean).join('——')}
                    </div>
                    <Space>
                      <ResumeFormItem label="学校" style={{ flex: 1 }}>
                        <Input v-model={educationItem.school} onChange={refreshRenderKey}/>
                      </ResumeFormItem>
                      <Tooltip message="删除该教育经历">
                        <Button icon="pi-close" style={{ flexShrink: 0 }}/>
                      </Tooltip>
                    </Space>
                    <Space style={{ alignItems: 'center' }}>
                      <ResumeFormItem label="时间" style={{ flex: 1 }}>
                        <Input v-model={educationItem.time} onChange={refreshRenderKey}/>
                      </ResumeFormItem>
                      <ResumeFormItem label="专业" style={{ flex: 1 }}>
                        <Input v-model={educationItem.program} onChange={refreshRenderKey}/>
                      </ResumeFormItem>
                    </Space>
                    <Space vertical>
                      {educationItem.content.map((_, index) => (
                        <ResumeFormItem label={`# ${index + 1}`} textAlign="center" key={index}>
                          <Input v-model={educationItem.content[index]} noClear onChange={refreshRenderKey}/>
                          <TextGeneratorButton valuePath={`education.data.${educationIndex}.content.${index}`}/>
                        </ResumeFormItem>
                      ))}
                    </Space>
                  </PageCardContent>
                );
              })}
            </PageCard>

            {/*---------------------------------------工作经历-------------------------------------------*/}
            <div className="page-body-title">工作经历</div>
            <PageCard>
              <PageCardContent>
                <ResumeFormItem label="标题">
                  <Input v-model={state.resumeInfo.experience.title} onChange={refreshRenderKey}/>
                </ResumeFormItem>
              </PageCardContent>
              {state.resumeInfo.experience.data.map((experienceItem, experienceIndex) => {
                return (
                  <PageCardContent key={experienceIndex}>
                    <div className="page-group-title">
                      {[experienceItem.company, experienceItem.role].filter(Boolean).join('——')}
                    </div>
                    <Space>
                      <ResumeFormItem label="公司" style={{ flex: 1 }}>
                        <Input v-model={experienceItem.company} onChange={refreshRenderKey}/>
                      </ResumeFormItem>
                      <Tooltip message="删除该工作经历">
                        <Button icon="pi-close"/>
                      </Tooltip>
                    </Space>
                    <Space style={{ alignItems: 'center' }}>
                      <ResumeFormItem label="时间" style={{ flex: 1 }}>
                        <Input v-model={experienceItem.time} onChange={refreshRenderKey}/>
                      </ResumeFormItem>
                      <ResumeFormItem label="岗位" style={{ flex: 1 }}>
                        <Input v-model={experienceItem.role} onChange={refreshRenderKey}/>
                      </ResumeFormItem>
                    </Space>
                    <Space vertical>
                      {experienceItem.content.map((_, index) => (
                        <ResumeFormItem label={`# ${index + 1}`} textAlign="center" key={index}>
                          <Input v-model={experienceItem.content[index]} noClear onChange={refreshRenderKey}/>
                          <TextGeneratorButton valuePath={`experience.data.${experienceIndex}.content.${index}`}/>
                        </ResumeFormItem>
                      ))}
                    </Space>
                  </PageCardContent>
                );
              })}
            </PageCard>

            {state.resumeInfo.externals.map((externalItem, externalIndex) => {
              return (
                <Fragment key={externalIndex}>
                  <div className="page-body-title">{externalItem.title}</div>
                  <PageCard>
                    <Space vertical>
                      {externalItem.content.map((_, index) => (
                        <ResumeFormItem label={`# ${index + 1}`} textAlign="center" key={index}>
                          <Input v-model={externalItem.content[index]} noClear onChange={refreshRenderKey}/>
                          <TextGeneratorButton valuePath={`externals.${externalIndex}.content.${index}`}/>
                        </ResumeFormItem>
                      ))}
                    </Space>
                  </PageCard>
                </Fragment>
              );
            })}
          </Scroll>
        </PageCard>
        <PageCard full className="page-body-right">
          <PageCardContent noPadding full>
            {!dataMetas.value.length ? (
              <div style={{ height: '100%', width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                <Button label="选择模板" icon="pi-bookmark" onClick={handler.changeTemplate} mode="fill" size="large"/>
              </div>
            ) : (<Scroll alwaysShowScrollbar>
              <div
                key={cmsRenderKey_a.value}
                data-cms-render={cmsRenderKey_a.value}
                style={{ display: state.currentCmsRender === 'a' ? '' : 'none' }}>
                <ReactCmsRender dataMetas={dataMetas.value}/>
              </div>
              <div
                key={cmsRenderKey_b.value}
                data-cms-render={cmsRenderKey_b.value}
                style={{ display: state.currentCmsRender === 'a' ? 'none' : '' }}>
                <ReactCmsRender dataMetas={dataMetas.value}/>
              </div>
            </Scroll>)}
          </PageCardContent>
        </PageCard>
      </div>
    </PageCard>
  );
});
